package cn.samir.sudoku.core;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import cn.samir.sudoku.util.Utils;

public class SubItemView extends View {
	public static final int DEFAULT_COLOR = Color.WHITE;// 默认的背景颜色
	public static final int SELECTED_COLOR = Color.YELLOW;// 选中区域的颜色
	public static final int MARK_COLOR = Color.RED;// 标记的颜色
	public static final int PREDEFTEXT_COLOR = Color.BLACK;// 预定义数字的颜色
	public static final int PREDEFBACK_COLOR = Color.GRAY;// 预定义背景的颜色
	public static final int INPUT_COLOR = 0xFF1E90FF;// 填写的字体颜色
	public static final int INPUT_ERR_COLOR = Color.RED;// 填写的字体颜色
	public static final int SELECTED_ONE_COLOR = 0xFFFFD39B;

	public static final int BORDER_LEFT = 0x01;
	public static final int BORDER_TOP = 0x02;
	public static final int BORDER_RIGHT = 0x04;
	public static final int BORDER_BUTTON = 0x08;
	public static final int BORDER_NULL = 0x00;
	public static final int VALUE_OK = 1;// 值正确
	public static final int VALUE_ERROR = 0;// 这个值错误
	public static final int VALUE_NULL = 2;// 没有值
	private int mIsValueOk = VALUE_NULL;// 这个标识只用于显示，如果不需要帮助，即使值为错误，value
										// 也可能＝VALUE_OK
	public int mFlagValueOk = VALUE_NULL;// 这个才是真正表示值是否是正确的
	private int[] mMarksNum = new int[9];// 标记
	// private int mValue;//
	private int mWidth;
	private int mHeight;
	private Paint mPaint;
	private Paint mBorderPaint;

	boolean isPreDefValue = false;
	private int mNormalBorderColor;
	private int mLargerBorderColor;
	int smallBorderWidth = 1;
	int bigerBorderWidth = 2;
	private int mDrawBorderType = BORDER_NULL;
	private boolean hasMarks = false;
	private boolean mIsSetValue = false;
	AddMarkListener mAddMarkListener = null;
	private int backgroundColor = Color.WHITE;
	public SudokuSubItem mSudokuSubItem;
	private ItemClickListener itemClickListener;

	public SubItemView(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		inits();
	}

	public SubItemView(Context context, AttributeSet attrs) {
		super(context, attrs);
		inits();

	}

	public ItemClickListener getItemClickListener() {
		return itemClickListener;
	}

	public void setItemClickListener(ItemClickListener itemClickListener) {
		this.itemClickListener = itemClickListener;
	}

	public boolean isPreDefValue() {
		return isPreDefValue;
	}

	public void setPreDefValue(int DefValue) {
		if (Utils.isNumberLegal(DefValue)) {
			// mSudokuSubItem.value = DefValue;
			setValue(DefValue);
			isPreDefValue = true;
			mFlagValueOk = VALUE_OK;
		} else {
			isPreDefValue = false;
		}
		// invalidate();
	}

	public int getmNormalBorderColor() {
		return mNormalBorderColor;
	}

	public void setmNormalBorderColor(int mNormalBorderColor) {
		this.mNormalBorderColor = mNormalBorderColor;
	}

	public int getmLargerBorderColor() {
		return mLargerBorderColor;
	}

	public void setmLargerBorderColor(int mLargerBorderColor) {
		this.mLargerBorderColor = mLargerBorderColor;
	}

	public SubItemView(Context context) {
		super(context);
		inits();
	}

	public void clearMark() {
		if (isPreDefValue)
			return;
		if (mIsSetValue)
			return;
		for (int i = 0; i < 9; i++) {
			mMarksNum[i] = 0;
		}
		hasMarks = false;
		invalidate();
	}

	public void clearValue() {
		if (isPreDefValue)
			return;
		if (mIsSetValue) {
			mSudokuSubItem.value = 0;
		}
		invalidate();
	}

	public SudokuSubItem getSudokuSubItem() {
		return mSudokuSubItem;
	}

	public void setSudokuSubItem(SudokuSubItem mSudokuSubItem) {
		if (mSudokuSubItem != null) {
			this.mSudokuSubItem = mSudokuSubItem;
			setBorderType(mSudokuSubItem.xPoint, mSudokuSubItem.yPoint);
		}

	}

	void setBorderType(int x, int y) {
		if ((x + 1) % 3 == 0) {
			mDrawBorderType |= BORDER_RIGHT;
		}

		if ((x != 0) && (x % 3 == 0)) {
			mDrawBorderType |= BORDER_LEFT;
		}

		if ((y + 1) % 3 == 0) {
			mDrawBorderType |= BORDER_BUTTON;
		}

		if ((y != 0) && (y % 3 == 0)) {
			mDrawBorderType |= BORDER_TOP;
		}

	}

	void inits() {
		mPaint = new Paint();
		mPaint.setAntiAlias(true);// 去除锯齿
		mPaint.setFilterBitmap(true);// 对位图进行滤波处理
		mSudokuSubItem = new SudokuSubItem();
		mBorderPaint = new Paint();
		mBorderPaint.setColor(Color.BLACK);
		mBorderPaint.setStrokeWidth(4);
		mNormalBorderColor = Color.DKGRAY;
		mLargerBorderColor = Color.BLACK;
	}

	public AddMarkListener getAddMarkListener() {
		return mAddMarkListener;
	}

	public void setAddMarkListener(AddMarkListener addMarkListener) {
		this.mAddMarkListener = addMarkListener;
	}

	public void addMark(int number) {
		if (Utils.isNumberLegal(number)) {
			if (mMarksNum[number - 1] == number) {
				removeMark(number);
				return;
			} else {
				mMarksNum[number - 1] = number;
			}
			mIsSetValue = false;
			hasMarks = true;
			invalidate();
		}
	}

	public void removeMark(int number) {
		if (Utils.isNumberLegal(number)) {
			if (mMarksNum[number - 1] != 0) {
				mMarksNum[number - 1] = 0;
			}
		}
		hasMarks = false;
		for (int i = 0; i < 9; i++) {
			if (mMarksNum[i] != 0) {
				hasMarks = true;
			}
		}
		invalidate();
	}

	public int getmValue() {
		return mSudokuSubItem.value;
	}

	public void setValue(int mValue) {
		if (isPreDefValue)
			return;
		if (Utils.isNumberLegal(mValue)) {
			mSudokuSubItem.value = mValue;
			mIsSetValue = true;
			if (hasMarks) {
				clearMark();
			}
		}
	}

	/**
	 * 设置判断后的值
	 * 
	 * @param mValue
	 *            值
	 * @param is_ok
	 *            是否可以在这个格里
	 */
	public void setValue(int value, int is_ok, int real) {
		mIsValueOk = is_ok;
		mFlagValueOk = real;
		setValue(value);
		invalidate();
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}

	@Override
	protected void onLayout(boolean changed, int left, int top, int right,
			int bottom) {
		super.onLayout(changed, left, top, right, bottom);
	}

	public void UsePaintColor(int resId) {
		mPaint.setColor(getContext().getResources().getColor(resId));
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		mWidth = getWidth();
		mHeight = getHeight();
		if (isPreDefValue) {// 预定义背景颜色
			canvas.drawColor(Color.LTGRAY);
		} else {
			canvas.drawColor(backgroundColor);
		}

		drawBorder(canvas);
		if (mIsSetValue) {

			// UsePaintColor(android.R.color.black);
			if (isPreDefValue) {// 预定义字体颜色
				mPaint.setColor(Color.BLACK);
			} else {
				mPaint.setColor(INPUT_COLOR);// 正确的
				// 不是预定义的数字，然后分为正确的显示的错误的显示
				if (mIsValueOk == VALUE_ERROR) {// 错误的
					mPaint.setColor(INPUT_ERR_COLOR);
				}
			}

			mPaint.setTextSize(mHeight * 9 / 10);
			// mPaint.setStrokeWidth(10);
			mPaint.setTypeface(Typeface.DEFAULT_BOLD);
			mPaint.setTextAlign(Align.CENTER);
			canvas.drawText(mSudokuSubItem.value + "", 0 + mHeight / 2, mHeight
					- mHeight / 5, mPaint);
		} else {
			// UsePaintColor(android.R.color.holo_red_dark);
			mPaint.setColor(MARK_COLOR);
			mPaint.setTypeface(Typeface.DEFAULT_BOLD);
			// mPaint.setStrokeWidth(mHeight / 10);
			mPaint.setTextSize(mHeight / 4);

			for (int i = 0; i < 9; i++) {// 标记值
				int value = mMarksNum[i];
				// value = i;
				if (Utils.isNumberLegal(value)) {
					// 00
					canvas.drawText(value + "", ((i % 3) * mWidth / 3)
							+ mHeight / 12, ((i + 3) / 3) * mHeight / 3
							- mHeight / 12, mPaint);
					// canvas.drawText(value + "", (i % 3) * mHeight / 3,
					// (int) (((i / 3) * mWidth / 3)), mPaint);

				}
			}
		}
	}

	private void drawBorder(Canvas canvas) {
		if ((mDrawBorderType & BORDER_BUTTON) == BORDER_BUTTON) {
			setLargerPaint();
		} else {
			setSmallerPaint();
		}
		canvas.drawLine(0, mHeight, mWidth, mHeight, mBorderPaint);
		if ((mDrawBorderType & BORDER_TOP) == BORDER_TOP) {
			setLargerPaint();
		} else {
			setSmallerPaint();
		}
		canvas.drawLine(0, 0, mWidth, 0, mBorderPaint);
		if ((mDrawBorderType & BORDER_RIGHT) == BORDER_RIGHT) {
			setLargerPaint();
		} else {
			setSmallerPaint();
		}
		canvas.drawLine(mWidth, 0, mWidth, mHeight, mBorderPaint);
		if ((mDrawBorderType & BORDER_LEFT) == BORDER_LEFT) {
			setLargerPaint();
		} else {
			setSmallerPaint();
		}
		canvas.drawLine(0, 0, 0, mHeight, mBorderPaint);
	}

	private void setSmallerPaint() {
		mBorderPaint.setColor(mNormalBorderColor);
		mBorderPaint.setStrokeWidth(smallBorderWidth);
	}

	private void setLargerPaint() {
		mBorderPaint.setColor(mLargerBorderColor);
		mBorderPaint.setStrokeWidth(bigerBorderWidth);
	}

	public int getDrawBorderType() {
		return mDrawBorderType;
	}

	public void setDrawBorderType(int mDrawBorderType) {

		this.mDrawBorderType = mDrawBorderType;
	}

	public int getBackgroundColor2() {
		return backgroundColor;
	}

	public void setBackgroundColor2(int backgroundColor) {
		if (isPreDefValue)
			return;
		this.backgroundColor = backgroundColor;
		invalidate();
	}

	@Override
	protected void onFocusChanged(boolean gainFocus, int direction,
			Rect previouslyFocusedRect) {
		super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
	}

	@SuppressLint("ClickableViewAccessibility")
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		Log.i(VIEW_LOG_TAG, "itemViewonTouchEvent");
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			if (itemClickListener != null) {
				Log.i(VIEW_LOG_TAG, "onItemClick");
				itemClickListener.onItemClick(this);
			}
		}
		return super.onTouchEvent(event);
	}

	@Override
	public String toString() {
		return mSudokuSubItem.toString();
	}

	public void clear() {
		if (isPreDefValue)
			return;
		hasMarks = false;
		mIsSetValue = false;
		mSudokuSubItem.value = 0;
		clearMark();
	}

	public boolean isHasMarks(int i) {
		if (!isHasMarks() || !Utils.isNumberLegal(i))
			return false;
		return (mMarksNum[i - 1] == i ? true : false);
	}

	public boolean isHasMarks() {
		return hasMarks;
	}

}
